﻿using Spider.Data;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Spider.Mvc
{
    public class SmartJsonFormatter : MediaTypeFormatter
    {
        public SmartJsonFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/json"));
            SupportedEncodings.Add(new UTF8Encoding(false,true));
            SupportedEncodings.Add(new UnicodeEncoding(false,true,true));
            MediaTypeMappings.Add(new XmlHttpRequestHeaderMapping());
        }
        public override bool CanReadType(Type type)
        {
            if (type == typeof(SmartObject))
            {
                return true;
            }
            return false;
        }

        public override bool CanWriteType(Type type)
        {
            if (type == typeof(SmartObject))
            {
                return true;
            }
            return false;
        }

        public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
        {
            byte[] bytes = new byte[readStream.Length];
            using (readStream)
            {
                readStream.Position = 0;
                readStream.Read(bytes, 0, bytes.Length);
                readStream.Close();
            }
            string json = Encoding.UTF8.GetString(bytes);
            return new Task<object>(() => SmartObject.Parse(json));

        }

        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            SmartObject o = value as SmartObject;
            byte[] bytes = Encoding.UTF8.GetBytes(o.ToJson());
            return new Task(() =>
            {
                using (writeStream)
                {
                    writeStream.Write(bytes, 0, bytes.Length);
                    writeStream.Close();
                }
            });            
        }
    }
}